package com.shelpe.services.sustainer.autoDrive;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class InprogressJobs {
	
	private Map<String, InprogressJob> jobs = new HashMap<String, InprogressJob>();
	
	public void registerInstance(String jobName, String instanceID){
		InprogressJob job = this.jobs.get(jobName);
		if(job == null){
			job = new InprogressJob();
			job.setJobName(jobName);
			jobs.put(jobName, job);
		}
		
		InprogressJobInstance ji = job.findByInstanceID(instanceID);
		if(ji != null){
			log.info("instance {} is already registered in job {}", instanceID, jobName);
			ji.setDriverID(null);
		}else{
			job.addInstance(instanceID);
		}
	}
	
	public boolean contain(String jobName, String driverID){
		InprogressJob job = this.jobs.get(jobName);
		if(job != null && job.instances != null){
			for(InprogressJobInstance inst:job.instances){
				if(inst.driverID != null && inst.driverID.equals(driverID) && inst.instanceID != null){
					log.info("the instance {} already acquire the driver {}", inst.instanceID, inst.driverID);
					return true;
				}
			}
		}
		return false;
	}
	
	public boolean hasFewJobsJob(String jobName){
		InprogressJob job = this.jobs.get(jobName);
		if(job == null || job.instances == null){
			return false;
		}
		InprogressJobInstance fewProductsJob = null;
		for(InprogressJobInstance inst:job.instances){
			if(inst.instanceID != null && inst.driverID != null && inst.products > 5){
				fewProductsJob = inst;
				break;
			}
		}
		if(fewProductsJob != null){
			log.info("there is more than 5 products auto driver job: {} - {}", fewProductsJob.instanceID, fewProductsJob.driverID);
			return true;
		}
		
		return false;
	}
	
	public void registerDriver(String jobName, String driverID, int products){
		InprogressJob job = this.jobs.get(jobName);
		if(job == null){
			job = new InprogressJob();
			job.setJobName(jobName);
			jobs.put(jobName, job);
		}
		
		if(job.instances != null && job.instances.size()>0){
			if(log.isDebugEnabled()){
				for(InprogressJobInstance inst:job.instances){
					log.debug("inprogress job: {}", inst);
				}
			}
			
			for(InprogressJobInstance inst:job.instances){
				if(inst.driverID == null){
					inst.driverID = driverID;
					inst.products = products;
				}
			}
		}else{
			log.info("there is no instance for job {} when driver {} register", jobName, driverID);
		}
	}
	
	public void unregister(String jobName, String instanceID){
		InprogressJob job = this.jobs.get(jobName);
		if(job != null){
			job.clearInstance(instanceID);
		}
	}

	@Data
	public static class InprogressJob{
		private String jobName;
		private List<InprogressJobInstance> instances;
		
		public void addInstance(String instanceID){
			if(this.instances == null){
				this.instances = new ArrayList<InprogressJobInstance>();
			}
			InprogressJobInstance iji = new InprogressJobInstance();
			iji.instanceID = instanceID;
			this.instances.add(iji);
		}
		
		public void clearInstance(String instanceID){
			if(this.instances != null){
				InprogressJobInstance found = null;
				for(InprogressJobInstance inst: this.instances){
					if(inst.instanceID!=null && inst.instanceID.equals(instanceID)){
						found = inst;
						break;
					}
				}
				if(found != null){
					this.instances.remove(found);
				}
			}
		}
		
		public InprogressJobInstance findByInstanceID(String instanceID){
			if(this.instances != null){
				for(InprogressJobInstance inst: this.instances){
					if(inst.instanceID!=null && inst.instanceID.equals(instanceID)){
						return inst;
					}
				}
			}
			return null;
		}
		
		public InprogressJobInstance findByDriverID(String driverID){
			if(this.instances != null){
				for(InprogressJobInstance inst: this.instances){
					if(inst.driverID!=null && inst.driverID.equals(driverID)){
						return inst;
					}
				}
			}
			return null;
		}
	}
	
	@Data
	public static class InprogressJobInstance{
		private String instanceID;
		private String driverID;
		private int products;
	}
}
